#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<sys/stat.h>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
using namespace std;

// 同一个文件名
const string filename = "/home/Czh_Linux/code/shared_memory";
// 同一个proj_id
const int proj_id = 2022044026;

// 建议设置为4096的整数倍
#define MEMORYSIZE 4096 // 设定的共享内存大小

// 获取唯一标识符
key_t GetKey()
{
    // 通过ftok算法形成一个唯一的key
    // 通过相同的filename、和project_id
    key_t key = ftok(filename.c_str(), proj_id);
    if (key < 0)
    {
        cerr << "errno: " << errno << ", errstring: " << strerror(errno) << endl;
        exit(1);
    }

    return key;
}

// 将key转化为16进制
string ToHex(int id)
{
    char buffer[1024];
    snprintf(buffer, sizeof(buffer), "0x%x", id);
    return buffer;
}

// 创建/打开 共享内存封装函数
int ShmOption(key_t key, int flag)
{

    // 参数(唯一标识符key，共享内存的大小，打开方式|权限)
    int shmid = shmget(key, MEMORYSIZE, flag); // 共享内存的id
    cout << shmid << endl;
    // key作为在内核中标识shm的唯一性
    // 对共享内存进行操作时，我们是通过shmid来进行的
    if (shmid < 0)
    {
        cerr << "shmid error: " << errno << ", errstring: " << strerror(errno) << endl;
        exit(2);
    }
    return shmid;
}

// 创建新的共享内存，并返回shmid
int CreateShm(key_t key)
{
    cout << "新的共享内存创建完成" << endl;
    // 创建，则需传入权限，并且通过O_EXCL防止重复创建，并且提供权限
    return ShmOption(key, IPC_CREAT | IPC_EXCL | 0644);
}

// 打开原有共享内存，并返回shmid
int GetShm(key_t key)
{
    // 打开，则只需通过O_CREAT打开
    return ShmOption(key, 0);
}
